package cmd

import (
	"flag"
	"strings"

	"api/system/helper"
	"api/system/vars"
)

type (
	MapStr  = vars.MapStr
	MMapStr = vars.MMapStr
)

var (
	dry     = helper.Dry
	join    = helper.Join
	trim    = helper.Trim
	empty   = helper.Empty
	appRoot = helper.GetRoot
	ucfirst = helper.UcFirst
)

const API_GROUP = "api"
const API_NAMESPACE = "app\\%v\\api"

type CmdParam struct {
	Path       string
	Table      string
	Suffix     string // 命名空间前缀，也就是 app\[service|controller|model|validate]\api后边的部分
	Model      string
	HasModel   bool
	Controller string
	Service    string
	Validate   string
	Group      string
	Field      MMapStr
}

func Parser() *CmdParam {
	var (
		paths    string // 想要解析的项目路径，一般项目路径下都会有数据库配置信息，因此不需要单独配置数据库信息
		suffix   string
		hasModel bool
		table    string // 要想创建的表名，记住，不要带表前缀
		field    string // 要在列表里显示的字段，没有指定则根据表里的字段注释进行解析，没有注释的则显示字段名称
	)

	flag.StringVar(&paths, "p", "", "要解析项目的路径")
	flag.StringVar(&suffix, "s", "", "命名空间后缀")
	flag.StringVar(&table, "t", "", "表名")
	flag.BoolVar(&hasModel, "m", false, "是否要生成数据表模型")
	flag.StringVar(&field, "f", "", "列表里显示以逗号分割的字段，例如：id=ID,name=名称:require,cate=分类:require")
	flag.Parse()

	if empty(paths) {
		paths = appRoot()
	}

	if empty(table) && empty(suffix) {
		dry("未包含前缀的表名或者命名空间后缀，至少提供一个，如果已提供，请注意是否有”-m“参数，有的话请注意其顺序，该参数务必放在最后，切记！")
	}

	if empty(table) {
		suffix = strings.ToLower(suffix)
		table = strings.ReplaceAll(suffix, "\\", "_")
	} else {
		table = strings.ToLower(trim(table))
	}

	// 列表显示字段
	fieldMap := parseField(field)

	// 模型命名空间处理
	model := handleNamespace(table, "model", suffix)
	controller := handleNamespace(table, "controller", suffix)
	service := handleNamespace(table, "service", suffix)
	validate := handleNamespace(table, "validate", suffix)

	return &CmdParam{
		Path:       paths,
		Table:      table,
		Field:      fieldMap,
		Model:      model,
		HasModel:   hasModel,
		Controller: controller,
		Service:    service,
		Validate:   validate,
		Group:      API_GROUP,
	}
}

func parseField(field string) MMapStr {
	fieldMap := make(MMapStr)
	if !empty(field) {
		field = trim(field)
		arr := strings.Split(field, ",")
		for _, val := range arr {
			tmp := strings.Split(val, "=")
			id := ""
			name := ""
			require := "false"
			if len(tmp) == 1 {
				id = tmp[0]
				name = tmp[0]
			} else {
				id = tmp[0]
				name = tmp[1]
			}

			if ridx := strings.Index(name, ":require"); ridx > 0 {
				require = "true"
				name = name[:ridx]
			}
			id = strings.Trim(id, " ")
			fieldMap[id] = map[string]string{
				"id":      id,
				"name":    strings.Trim(name, " "),
				"require": require,
			}
		}
	}

	return fieldMap
}

func handleNamespace(table, ctype string, suffixs ...string) string {
	suffix := ""
	if len(suffixs) > 0 && suffixs[0] != "" {
		suffix = suffixs[0]
	}

	modelSpace := []string{"app", ctype, API_GROUP}
	if empty(suffix) { // 没有传递命名空间后缀的话
		if strings.Index(table, "_") > 0 {
			tableArr := strings.Split(table, "_")
			if ctype == "controller" || ctype == "model" || ctype == "service" {
				lastElem := tableArr[len(tableArr)-1]
				tableArr[len(tableArr)-1] = ucfirst(lastElem)
			}
			modelSpace = append(modelSpace, tableArr...)
		} else {
			if ctype == "controller" || ctype == "model" || ctype == "service" {
				modelSpace = append(modelSpace, ucfirst(table))
			} else {
				modelSpace = append(modelSpace, table)
			}
		}
	} else {
		if strings.Index(suffix, "\\") > 0 {
			if suffix[:3] == "app" {
				modelSpace = strings.Split(suffix, "\\")
			} else {
				suffix = strings.ToLower(suffix)
				suffixArr := strings.Split(suffix, "\\")
				if ctype == "controller" || ctype == "model" || ctype == "service" {
					lastElem := suffixArr[len(suffixArr)-1]
					suffixArr[len(suffixArr)-1] = ucfirst(lastElem)
				}
				modelSpace = append(modelSpace, suffixArr...)
			}
		} else {
			if ctype == "controller" || ctype == "model" || ctype == "service" {
				modelSpace = append(modelSpace, ucfirst(table))
			} else {
				modelSpace = append(modelSpace, table)
			}
		}
	}

	if ctype == "model" {
		modelSpace[2] = "admin"
	}

	return join("\\", modelSpace...)
}
